<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Document</title>
</head>

<body>
  <script>
    //关于继承的综合练习
    //已知Shape类（形状）、Square类（正方形）、Circle类（圆形）之间的继承关系如下类图所示，
    //其中Square类（正方形）和Circle类（圆形）都继承于Shape（形状）

    //Shape（形状）拥有周长属性、周长面积属性、类型属性，还有一个输出类型方法
    //Square（正方形）有输出周长方法、输出面积方法，还有一个边长属性
    //Circle（圆形）有输出周长方法、输出面积方法，还有一个半径属性

    //Part 1 通过ES5的（原型继承+构造继承）来实现该案例///////////////////////////
    function Shape(perimeter,area,type) { //周长、面积、类型
      this.perimeter = perimeter;
      this.area = area;
      this.type = type;
    };
    Shape.prototype.showType = function () {
      switch (this.type) { //可优化代码，用this.constructor.name判断也可以，那样就不用传类型参数了
        case "Circle":
          console.log("圆形")
          break;
        case "Square":
          console.log("正方形")
          break;
        default:
          break;
      }
    };

    function Square(sideLength, type) {//边长、类型
      Shape.call(this, sideLength*4, sideLength*sideLength,type);
      this.sideLength = sideLength;
    }
    Square.prototype.showPerimeter = function () { console.log(this.perimeter) }

    function Circle(radius, type) { //半径、类型
      Shape.call(this, 2*Math.PI*radius, Math.PI*radius*radius,type);
      this.radius = radius;
    }
    Circle.prototype.showArea = function () { console.log(this.area) }

    Square.prototype.__proto__ = Shape.prototype;
    Circle.prototype.__proto__ = Shape.prototype;
    var s1 = new Square(20, "Square");//通过s1.constructor.name能够得到类型，可以进一步优化代码，去除type参数
    var c1 = new Circle(10, "Circle");//半径是10的圆形

    s1.showType();
    s1.showPerimeter();

    c1.showType();
    c1.showArea();


    //Part 2-1 通过ES6的class来实现该案例////////////////////////////
    class Shape{
      constructor(perimeter,area,type) { //周长、面积、类型
        this.perimeter = perimeter;
        this.area = area;
        this.type = type;
      }
      showType () {
        switch (this.type) { //可优化代码，用this.constructor.name判断也可以
        // switch (this.constructor.name) { //用this.constructor.name判断也可以，那样就不用传类型参数了
          case "Circle":
            console.log("圆形");
            break;
          case "Square":
            console.log("正方形");
            break;
          default:
            break;
        }
      };
    }
    
    class Square extends Shape{
      constructor(sideLength, type) { //边长、类型
        super(sideLength*4, sideLength*sideLength,type);
        this.sideLength = sideLength;
      }
      showPerimeter() { console.log(this.perimeter) }
    }

    class Circle extends Shape{
      constructor(radius, type) { //半径、类型
        super(2*Math.PI*radius, Math.PI*radius*radius,type);
        this.radius = radius;
      }
      showArea() { console.log(this.area) }
    }

    var s1 = new Square(20, "Square");//通过s1.constructor.name能够得到类型，可以进一步优化代码
    var c1 = new Circle(10, "Circle");//半径是10的圆形

    s1.showType();
    s1.showPerimeter();

    c1.showType();
    c1.showArea();
    
    //Part 2-2 ///////优化代码//////////
    class Shape{
      constructor(perimeter,area) { //周长、面积
        this.perimeter = perimeter;
        this.area = area;
      }
      showType () {
       switch (this.constructor.name) { //用this.constructor.name判断也可以，那样就不用传类型参数了
          case "Circle":
            console.log("圆形");
            break;
          case "Square":
            console.log("正方形");
            break;
          default:
            break;
        }
      };
    }
    
    class Square extends Shape{
      constructor(sideLength) { //边长、类型
        super(sideLength*4, sideLength*sideLength);
        this.sideLength = sideLength;
      }
      showPerimeter() { console.log(this.perimeter) }
    }

    class Circle extends Shape{
      constructor(radius) { //半径、类型
        super(2*Math.PI*radius, Math.PI*radius*radius);
        this.radius = radius;
      }
      showArea() { console.log(this.area) }
    }

    var s1 = new Square(20);
    var c1 = new Circle(10);

    s1.showType();
    s1.showPerimeter();

    c1.showType();
    c1.showArea();
  </script>
</body>

</html>